#pragma once
#include <windows.h>
#include <cstdio>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <d3d9.h>
#include <d3dx9.h>
#include "../utility/defs.h"
#include "../utility/Gets.h"
#include "../utility/math.h"

using namespace std;

struct md5Mesh;
struct Joint;
struct Mesh;
struct Vert;
struct Tri;
struct Weight;

/*
===================
	md5mesh
===================
*/
struct Md5Mesh
{
	int numJoints;
	int numMeshes;
	vector<Joint> vecJoint;
	vector<Mesh> vecMesh;	
};

struct Joint
{
	string bonename;
	int parentIndex;
	D3DXVECTOR3 pos;
	D3DXQUATERNION orient;
	D3DXMATRIX matOrient;
};

struct Vert
{
	D3DXVECTOR2 texUV;
	int weightIndex;
	int weightElem;  
};
struct Tri
{
	int vertIndex1;
	int vertIndex2;
	int vertIndex3;
};

struct Weight
{
	int jointIndex;
	float weightValue;
	D3DXVECTOR3 pos;
};

struct Mesh
{
	string shader;		
	int numVerts;	
	int numTris;
	int numWeights;		
	vector<Vert> vecVerts;
	vector<Tri> vecTris;
	vector<Weight> vecWeights;
};

/*
================
	md5anim
================
*/

struct Md5Anim;
struct Hierachy;
struct Bounds;
struct Baseframe;
struct Frame;

struct Md5Anim
{
	Md5Anim():numFrames( 0 ),numJoints( 0 ),frameRate( 0 ),
	numAnimatedComponents( 0 ){
	}
	int numFrames;
	int numJoints;
	int frameRate;
	int numAnimatedComponents;

	vector<float> vecOffset;
	vector<Hierachy> vecHierachy;
	vector<Bounds> vecBounds;
	vector<Baseframe> vecBaseframe;
	vector<Frame> vecFrame;
};

struct Hierachy	//Joints
{
	string jointName;
	int parentIndex;
	int numComp;		//flags
	int frameIndex;
};

struct Bounds //numframe
{
	D3DXVECTOR3 min;
	D3DXVECTOR3 max;
};

struct Baseframe //numJoint
{
	D3DXVECTOR3 pos;
	D3DXQUATERNION orient;
	D3DXMATRIX mat;
};

struct Frame  //numframe
{
	Frame():frameIndex( 0 ){

	}
	int frameIndex;
	vector<float> vecAnimatedComp; //numanimatedComponent
};

/*
==============
	material
==============
*/
struct Mtr;

struct Mtr
{
	// map< modelname, diffusemap >
	map< string, string > mapDiffuse;
	map< string, string > mapNormal;
};

/*
================
	cMd5Viewer
================
*/


class cMd5Viewer
{
public:
	void ReadMd5Mesh( Md5Mesh& md5mesh, string filename );
	void ReadMd5Anim( Md5Anim& md5anim, string filename );
	void ReadMtr( Mtr& mtr, string filename );
private:
	//md5mesh
	void GetJoints( ifstream& fin, Joint& joint );
	void GetMesh( ifstream& fin, Mesh& mesh );

	//md5anim
	void GetHierachy( ifstream& fin, Hierachy& hierachy );
	void GetBound( ifstream& fin, Bounds& bounds );
	void GetBaseframe( ifstream& fin, Baseframe& baseframe );
};
